

import ajax from './ajax';
import GltfParser from './gltfParser';

class GLTFLoader{
    static load(url,callback){
        ajax({url:url}).then((gltf)=>{
            let gltfParser = new GltfParser(gltf);
            let primitives = gltfParser.getPrimitives();
            if(primitives.length < 1){
                callback(new Error('primitives.length < 1'));
            }else{
                primitives.forEach(primitive=>{
                    console.log('primitive:',primitive);
                    let meshInfo = GLTFLoader.getVertexInfo(primitive);
                    callback(null,meshInfo);
                });
            }
        }).catch((err)=>{
            console.error(`load url:${url} error:${err}`);
        })
    }

    static containNormalInfo(attr){
        for(let i = 0; i < attr.length; ++i){
            let item = attr[i];
            let name = item.name;
            if(name.endsWith('normals')){
                return true;
            }
        }
        return false;
    }

    static getNormalItem(attr){
        for(let i = 0; i < attr.length; ++i){
            let item = attr[i];
            let name = item.name;
            if(name.endsWith('normals')){
                return item;
            }
        }
        return null;
    }

    static getVertexInfo(primitive) {

        //  验证三角形环绕方式
        if(primitive.mode !== 4){
            /**
             * 0: POINTS
             * 1: LINES
             * 2: LINE_LOOP
             * 3: LINE_STRIP
             * 4: TRIANGLES
             * 5:TRIANGLE_STRIP
             * 6:TRIANGLE_FAN
             */
            throw new Error('暂只支持 TRIANGLES!');
        }

        // 索引信息
        let indices = primitive.indices.srcData;

        // 所有的顶点信息
        // 顶点信息
        let attrs = primitive.attributes;
        let vInfo = attrs[0];
        // 验证类型 (FLOAT)
        if(vInfo.componentType !== 5126){
            throw new Error('vertex暂不支持其他类型!');
        }

        let vertexs = vInfo.srcData; // float array

        // 判断是否包含法线信息,如果不包含,则手工计算法线
        let normals;
        if(GLTFLoader.containNormalInfo(attrs)){
            let normalItem = GLTFLoader.getNormalItem(attrs);
            if(normalItem.componentType !== 5126){
                throw new Error('normal暂不支持其他类型!');
            }
            normals = normalItem.srcData;
        }else{

            normals = new Array(vertexs.length);

            // 手工计算顶点法线
            let all = {};
            let faceCount = Math.floor(indices.length / 3);

            let v01 = cc.v3();
            let v12 = cc.v3();
            let v0 = cc.v3();
            let v1 = cc.v3();
            let v2 = cc.v3();
            let tmpNormal = cc.v3();
            for(let i = 0; i < faceCount; ++i){
                let i0 = indices[3 * i];
                let i1 = indices[3 * i + 1];
                let i2 = indices[3 * i + 2];
                cc.Vec3.set(v0,vertexs[3 * i0],vertexs[3 * i0 + 1],vertexs[3 * i0 + 2]);
                cc.Vec3.set(v1,vertexs[3 * i1],vertexs[3 * i1 + 1],vertexs[3 * i1 + 2]);
                cc.Vec3.set(v2,vertexs[3 * i2],vertexs[3 * i2 + 1],vertexs[3 * i2 + 2]);

                cc.Vec3.subtract(v01,v1,v0);
                cc.Vec3.subtract(v12,v2,v1);
                cc.Vec3.cross(tmpNormal,v01,v12);
                cc.Vec3.normalize(tmpNormal,tmpNormal);
                if(!all[i0]){
                    all[i0] = [];
                }
                all[i0].push([tmpNormal.x,tmpNormal.y,tmpNormal.z]);

                if(!all[i1]){
                    all[i1] = [];
                }
                all[i1].push([tmpNormal.x,tmpNormal.y,tmpNormal.z]);

                if(!all[i2]){
                    all[i2] = [];
                }
                all[i2].push([tmpNormal.x,tmpNormal.y,tmpNormal.z]);
            }

            //  求平均值
            for(let k in all){
                let idx = parseInt(k);
                let arr = all[k];
                let dlen = 1 / (arr.length || 1);
                let x = 0,y = 0,z = 0;
                arr.forEach(item=>{
                    x += item[0];
                    y += item[1];
                    z += item[2];
                });

                cc.Vec3.set(tmpNormal,x * dlen, y * dlen,z * dlen);
                cc.Vec3.normalize(tmpNormal,tmpNormal);

                normals[3 * idx] = tmpNormal.x;
                normals[3 * idx + 1] = tmpNormal.y;
                normals[3 * idx + 2] = tmpNormal.z;
            }
        }

        // TODO:
        // 其余的信息, 如:
        // uv  normal  material 等后面处理

        //  还包含aabb
        let min = vInfo.min;
        let max = vInfo.max;
        return {
            vertexs,
            normals,
            indices,
            min,
            max,
        }
    }
}


/**
 *
 * demo:
 * GLTFLoader.load('/demos/assets/Love.gltf',(err,meshInfo)=>{
   if(err){
       throw err;
   }
   let mesh = new Mesh(meshInfo);
});

 */

export default GLTFLoader;
